\(~\)
R se puede usar como calculadora. Puedes escribir las operaciones y ejecutarlas en la consola. Por ejemplo, la suma de dos valores:
3 + 6
## [1] 9
(2 + 2)* 10
## [1] 40
R también realiza operaciones más complejas como logaritmos o senos y cosenos (etc.):
log(20)
## [1] 2.995732
cos(4)
## [1] -0.6536436
También puedes escribir las operaciones en el script y ejecutarlo haciendo click en el botón Run situado en la parte superior derecha de la ventana del script. De esta manera, puedes ir creando un script con todo el código que quieras.
Prueba a ejecutar el siguiente comando desde el script:
print("Hello World!")
## [1] "Hello World!"
\(~\)
\(~\)
El directorio de trabajo es la caperta de tu ordenador en la que estás trabajando. Cuando lees un archivo con R, R lo busca en el directorio de trabajo que le has especificado. Cuando guardas un archivo de datos o una figura con R, R la guarda en el directorio de trabajo especificado.
getwd()
setwd("/path/to/directory")
\(~\)
Cuando instalamos R por primera vez, lo que estamos instalando se conoce como “R Base”, es decir, las funcionalidades básicas de R. Una de las ventajas de R es que, al ser un lenguaje de código abierto, la propia comunidad de R desarrolla nuevas extensiones de R; estas extensiones se conocen como librerías o paquetes de R.
Hay muchos paquetes disponibles, se encuentran sobre todo en el repositorio oficial de librerias de R: CRAN. Para poder usar un paquete (por ejemplo, “dplyr”) hay que instalarlo en el ordenador y cargarlo en R, de la siguiente manera:
install.packages("dplyr")
library("dplyr")
En la pestaña “Packages” de la ventana inferior izquierda de RStudio se pueden ver los paquetes instalados. Los paquetes ya cargados aparecen con un ✓. Otra manera de cargar paquetes es haciendo click directamente en el en la casilla correspondiente al paquete:
\(~\)
\(~\)
Los paquetes de R suelen estar, en general, bastante bien documentados; cuentan con información y ayuda para el usuario sobre las funcionalidades, así como ejemplos sencillos de la manera de usar las funciones del paquete. Hay dos principales fuentes de ayuda referentes a los paquetes:
help("dplyr")
\(~\)
Una práctica de buen uso en la programación es comentar el código que vamos desarrollando. De esta manera, será más fácil de entender el código si volvemos a abir el script después de un tiempo o lo compartimos con otras personas. En R, cualquier texto despúes de un # no se ejecuta.
# Esto no se ejecuta
\(~\)
Ejercicios
\(~\)
\(~\)
\(~\)
Una variable es una letra o palabra que almacena un valor. Para asignar un valor a una variable se utiliza el operador de asignación <-:
x <- 3
MiNumero <- 9
Ahora, x se denomina una variable y aparece en la ventana superior derecha de RStudio workspace window. En esta ventana aparecerán todos los objetos que vayamos guardando durante la sesión. R los almacena en la memoria de manera que puedan ser usados más adelante.
Si ahora escribimos el nombre de la variable, el valor de ésta se imprimirá en la consola:
x
## [1] 3
Hay algunas variables especiales predefinidas en R, como por ejemplo el número Pi:
pi
## [1] 3.141593
Ahora, podemos hacer operaciones con/entre las variables:
x + 2
## [1] 5
x + MiNumero
## [1] 12
Y almacenarlas en nuevas variables:
y = x * 2
y
## [1] 6
Cambiar el valor de una variable:
y = 2500
y
## [1] 2500
O reescribirlas:
y = y + 1
y
## [1] 2501
\(~\)
Ejercicio
a y bcon valores 100 y 20, correspondientemente y una nueva variable z que sea la división de a entreb.\(~\)
\(~\) Los vectores son una sequencia de valores y en R se crean usando c():
x <- c(1, 2, 3);
x
## [1] 1 2 3
is.numeric(x)
## [1] TRUE
x <- c("a", "b", "c");
x
## [1] "a" "b" "c"
is.character(x)
## [1] TRUE
Podemos acceder a los elementos de los vectores haciendo uso de los corchetes [] y el índice correspondiente:
x[1]
## [1] "a"
Y podemos saber si se cumple una condición en un vector:
x == "a"
## [1] TRUE FALSE FALSE
y dónde:
which(x == "a")
## [1] 1
Podemos nombrar los elementos de un vector con names():
miVec <- c(1, 2, 3)
names(miVec) <- c("col1", "col2", "col3")
miVec
## col1 col2 col3
## 1 2 3
Podemos concatenar dos vectores:
v1 <- c(1, 2, 3)
v2 <- c(4, 5, 6)
v3 <- c(v1, v2)
v3
## [1] 1 2 3 4 5 6
Y consultar la longitud de un vector con la function length():
length(v3)
## [1] 6
Se pueden hacer operaciones con vectores (suma, resta…) por elementos utilizando los operadores normales. Si queremos hacer una multitplicación vectorial (matemáticamente hablando, el producto escalar) hay que usar el operador de mutiplicación matemática %*%:
v1 * v2
## [1] 4 10 18
v1 %*% v2
## [,1]
## [1,] 32
\(~\)
Ejercicios:
\(~\)
matrix():miMat <- matrix(v3, nrow = 2, ncol = 3, byrow = TRUE)
miMat
## [,1] [,2] [,3]
## [1,] 1 2 3
## [2,] 4 5 6
Dado un objeto, puedes prefuntarle a R qué tipo de objeto es tilizando la function class():
class(v3)
## [1] "numeric"
class(miMat)
## [1] "matrix"
data.frame():v1 <- c(1, 2, 3)
v2 <- c("a", "b", "c")
miDF <- data.frame(Col1 = v1, Col2 = v2)
miDF
## Col1 Col2
## 1 1 a
## 2 2 b
## 3 3 c
Para acceder a los elementos de una matriz, accedemos de la misma manera que a los elementos de los vectores, es decir, utilizando []. Pero en este caso, al tener las matrices dos dimensiones, tendremos que especificarle la fila y la columna del elemento al que queremos acceder. Por ejemplo, para acceder al elemento que está en la primera fila, en la segunda columna, haremos:
miMat[1,2]
## [1] 2
Podemos crear matrices de zeros, de unos o de NA-s, que es el “vacio” en R:
matrix(0, nrow = 4, ncol = 2)
## [,1] [,2]
## [1,] 0 0
## [2,] 0 0
## [3,] 0 0
## [4,] 0 0
matrix(1, nrow = 2, ncol = 3)
## [,1] [,2] [,3]
## [1,] 1 1 1
## [2,] 1 1 1
matrix(NA, nrow = 3, ncol = 3)
## [,1] [,2] [,3]
## [1,] NA NA NA
## [2,] NA NA NA
## [3,] NA NA NA
Podemos unir matrices por fila o columna, utilizando rbind() ycbind(), correspondientemente:
miMat1 <- matrix(v3, nrow = 2, ncol = 3, byrow = TRUE)
miMat2 <- matrix(v3, nrow = 2, ncol = 3, byrow = FALSE)
rbind(miMat1, miMat2)
## [,1] [,2] [,3]
## [1,] 1 2 3
## [2,] 4 5 6
## [3,] 1 3 5
## [4,] 2 4 6
cbind(miMat1, miMat2)
## [,1] [,2] [,3] [,4] [,5] [,6]
## [1,] 1 2 3 1 3 5
## [2,] 4 5 6 2 4 6
\(~\)
Ejercicio
\[ \begin{pmatrix} 1 & 4 & 3\\ 8 & 5 & 1 \end{pmatrix} \begin{pmatrix} 9 & 1 & 6\\ 7 & 6 & 4 \\ 3 & 2 & 1 \end{pmatrix} \]
\(~\)
\(~\)
Una función es una interfaz a la que el usuario le da un(os) argumento(s) (input) y ésta le devuelve un resultado (output) que es el resultado de haber realizado operaciones al input. Por ejemplo, la función sqrt(x) calcula la raíz cuadrada de x:
sqrt(9)
## [1] 3
Para calcular la media de 3 números, podemos calcularla a mano:
(3 + 4 + 5) / 3
## [1] 4
O podemos calcular utilizando la funcion mean():
x <- c(3, 4, 5)
mean(x)
## [1] 4
Otro ejemplo muy útil es seq() para crear secuencias. Utilizando el operador a:b, R nos devuelve la secuencia entre ay b, mientras que si queremos la secuencia cada 2 números hacemos uso de seq():
1:10
## [1] 1 2 3 4 5 6 7 8 9 10
seq(from = 1, to = 10, by = 2)
## [1] 1 3 5 7 9
Otra función básica como útil es rep(), que repite el argumento de la primera posición tantas veces como le indiques en la segunda posición; es decir:
rep(1, 10)
## [1] 1 1 1 1 1 1 1 1 1 1
rep(c(1, 2, 3), 5)
## [1] 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3
Podemos usar estas funciones para operar con vectores:
v <- 1:20
v
## [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
v[seq(1, 20, 2)]
## [1] 1 3 5 7 9 11 13 15 17 19
v[1:5] <- 0
v
## [1] 0 0 0 0 0 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
\(~\)
Recuerda
\(~\)
Algunas veces los agumentos tienen valores por defecto (default), de manera que si el usuario no especifica ninguna valor se utilizar ese. Por ejemplo, la función rnorm(), que genera n número aleatorios que siguen una distribución normal de media 0 y desviación estándar 1:
rnorm(n = 10)
## [1] -0.12875912 0.45299008 0.90290671 -0.09559665 -1.10301742
## [6] -1.88962689 0.18541214 1.05043756 0.26262529 -1.82484618
¿Cómo hacemos si queremos cambiar la media y desviación estándar?
\(~\)
Para consultar información sobre una función (qué es lo que hace, qué argumentos recibe, las opciones…) contamos con la ayuda R. Para acceder a la ayuda de una función, tecleamos ? y el nombre de la función:
?rnorm
help(rnorm)
Aparecerá una ficha de información con las siguientes secciones:
Description: El objetivo de la función
Usage: El modo de usarla
Arguments: Una lista de los argumentos que recibe
Details: Información más detallada de la función y sus argumentos
Value: Información a cerca del output de la función
References: Referencias de artículos útiles
Examples: Ejemplos de uso
De esta manera, si queremos generar 10 números aleatorios siguiendo una distribución normal de media 2 y desviación estándar 5:
rnorm(n = 10, mean = 2, sd = 5)
## [1] 8.1371703 -2.0259931 -2.3906344 7.7348243 1.6833709 1.0165176
## [7] 6.8347488 -0.7816868 5.7093931 -2.9785031
\(~\)
Un nivel superior consiste en definir las propias funciones con function(). Para definir una función necesitamos:
Un nombre
Al menos un input
Un output
Y se define de la siguiente manera:
NombreDeLaFucion <- function(input){
operaciones
return(output)
}
Por ejemplo, podemos crear una función que, dado un número te devuela la raiz cuadráda del triple de ese número:
MiPrimeraFuncion <- function(x) {
y <- sqrt(3 * x)
return(y)
}
MiPrimeraFuncion(20)
## [1] 7.745967
MiPrimeraFuncion(5)
## [1] 3.872983
\(~\)
Ejercicio:
Crea una función que dados 2 números:
MiSegundaFuncion <- function(a,b) {
x <- 1:a
y <- seq(a, b, by = 2)
x.y <- c(x,y)
x.y.sd <- sd(x.y)
sd2 <- x.y[1]*x.y.sd
return(c(x.y.sd, sd2))
}
MiSegundaFuncion(a = 3, b = 100)
## [1] 30.02922 30.02922
Hay muchas formas de importar (leer) y exportar (escribir) datos en R.
En las secciones 3, 4 y 5 estaremos trabajando con los siguientes conjuntos de datos:
gapminder: Es un conjunto de datos del paquete gapminder, con información sobre la esperanza de vida, el GDP per cápita, y población para 142 países. La información es quinquenal entre 1952 y 2007. En total se tienen 1704 registros en 6 variables.
UN98: Es un conjunto de datos del paquete carData, con información sobre indicadores sociales de las Naciones unidas para 207 países en el año 1998. En total se tienen 207 registros en 13 variables.
txhousing: Es un conjunto de datos del paquete ggplot2, con información sobre el mercado inmobiliario en el estado de Texas. Se cuenta con información mensual para 46 ciudades, entre los años 2000 y 2015. En total se tienen 8602 registros en 9 variables.
titanic3: Es un conjunto de datos del paquete PASWR. El conjunto de datos contiene información sobre l@s pasajer@s del barco Titanic. Está formado por 1309 observaciones (pasajer@s) y contamos con información de 14 variables.
La forma más sencilla de aprender a importar datos es usando la opción Import Dataset en la pestaña Environment de RStudio
\(~\)
\(~\)
También puedes leer datos directamente desde la consola usando la función read_excel() del paquete readxl (para archivos con extensión .xlsx o .xls).
Por ejemplo, si queremos leer la base de datos txhousing.xlsx podremos usar el siguiente código:
library(readxl)
data.house <- read_excel("txhousing.xlsx")
str(data.house)
## Classes 'tbl_df', 'tbl' and 'data.frame': 8602 obs. of 9 variables:
## $ city : chr "Abilene" "Abilene" "Abilene" "Abilene" ...
## $ year : num 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 ...
## $ month : num 1 2 3 4 5 6 7 8 9 10 ...
## $ sales : num 72 98 130 98 141 156 152 131 104 101 ...
## $ volume : num 5380000 6505000 9285000 9730000 10590000 ...
## $ median : num 71400 58700 58100 68600 67300 66900 73500 75000 64500 59300 ...
## $ listings : num 701 746 784 785 794 780 742 765 771 764 ...
## $ inventory: num 6.3 6.6 6.8 6.9 6.8 6.6 6.2 6.4 6.5 6.6 ...
## $ date : num 2000 2000 2000 2000 2000 ...
Para leer datos con extensión .csv o .txt puedes usar la función read.table().
Por ejemplo, si queremos leer la base de datos UN98.csv podremos usar el siguiente código:
data.gap <- read.table("gapminder.csv", header = TRUE, sep = "", dec = ",")
str(data.gap)
## 'data.frame': 1704 obs. of 6 variables:
## $ country : Factor w/ 142 levels "Afghanistan",..: 1 1 1 1 1 1 1 1 1 1 ...
## $ continent: Factor w/ 5 levels "Africa","Americas",..: 3 3 3 3 3 3 3 3 3 3 ...
## $ year : int 1952 1957 1962 1967 1972 1977 1982 1987 1992 1997 ...
## $ lifeExp : num 28.8 30.3 32 34 36.1 ...
## $ pop : int 8425333 9240934 10267083 11537966 13079460 14880372 12881816 13867957 16317921 22227415 ...
## $ gdpPercap: num 779 821 853 836 740 ...
Ejercicio
.txt (por ejemplo, UN98.txt)Otra opción es descargar datos directamente de internet. Para esto usamos la función read_csv del paquete readr.
library(readr)
data.mtcars <- read.csv("https://github.com/tidyverse/readr/raw/master/inst/extdata/mtcars.csv")
str(data.mtcars)
## 'data.frame': 32 obs. of 11 variables:
## $ mpg : num 21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
## $ cyl : int 6 6 4 6 8 6 8 4 4 6 ...
## $ disp: num 160 160 108 258 360 ...
## $ hp : int 110 110 93 110 175 105 245 62 95 123 ...
## $ drat: num 3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ...
## $ wt : num 2.62 2.88 2.32 3.21 3.44 ...
## $ qsec: num 16.5 17 18.6 19.4 17 ...
## $ vs : int 0 0 1 1 0 1 0 1 1 1 ...
## $ am : int 1 1 1 0 0 0 0 0 0 0 ...
## $ gear: int 4 4 4 3 3 3 3 4 4 4 ...
## $ carb: int 4 4 1 1 2 1 4 2 2 4 ...
Además, si estás interesado en los datos de EUROSTAT, del INE, o del Banco Mundial (paquetes WDI y `wbstats), puedes acceder a ellos haciendo web scraping a través de APIs.
Para exportar datos de R a excel (para archivos con extensión .xlsx o .xls), podremos usar la función write.xlsx() del paquete xlsx o del paquete openxlsx.
Por ejemplo, previamente, leímos los datos txhousing. Ahora prueba a exportarlos a excel. Verifica que tienes el nuevo archivo en tu directorio de trabajo.
library(openxlsx)
write.xlsx(data.house, "mis_datos.xlsx", row.names = FALSE)
\(~\)
Para exportar datos de R a archivos con extensión .csv o .txt, podremos usar la función write.table(). Nota: Ten en cuenta que estos formatos no admiten más de una hoja por archivo.
write.table(data.house, "mis_datos.csv", row.names = FALSE)
Ejercicio
.txt (por ejemplo, txhousing)Los datos también pueden ser guardados en un archivo con una extensión propia de R (.Rdata). Tiene como ventaja que si has modificado la clase de alguna de las variables, este formato lo conserva. Además es bastante eficiente y te permite también guardar varios objetos en el mismo archivo. Para guardar los datos se usa la función save(), y para leerlos se usa la función load()
save (data.house, data.gap, file = "mis_datos.Rdata")
load ("mis_datos.Rdata")
Después de importar tus datos, el siguiente paso sería verificar que fueron correctamente leídos y que las variables tienen la clase correcta para su posterior análisis. En R existen varias funciones que nos permiten explorar la estructura inicial de nuestros datos. Algunas de ellas son: View(), head(), tail(), str() y summary().
Por ejemplo, para los datos de gapminder
View(data.gap)
head(data.gap)
## country continent year lifeExp pop gdpPercap
## 1 Afghanistan Asia 1952 28.801 8425333 779.4453
## 2 Afghanistan Asia 1957 30.332 9240934 820.8530
## 3 Afghanistan Asia 1962 31.997 10267083 853.1007
## 4 Afghanistan Asia 1967 34.020 11537966 836.1971
## 5 Afghanistan Asia 1972 36.088 13079460 739.9811
## 6 Afghanistan Asia 1977 38.438 14880372 786.1134
tail(data.gap)
## country continent year lifeExp pop gdpPercap
## 1699 Zimbabwe Africa 1982 60.363 7636524 788.8550
## 1700 Zimbabwe Africa 1987 62.351 9216418 706.1573
## 1701 Zimbabwe Africa 1992 60.377 10704340 693.4208
## 1702 Zimbabwe Africa 1997 46.809 11404948 792.4500
## 1703 Zimbabwe Africa 2002 39.989 11926563 672.0386
## 1704 Zimbabwe Africa 2007 43.487 12311143 469.7093
str(data.gap)
## 'data.frame': 1704 obs. of 6 variables:
## $ country : Factor w/ 142 levels "Afghanistan",..: 1 1 1 1 1 1 1 1 1 1 ...
## $ continent: Factor w/ 5 levels "Africa","Americas",..: 3 3 3 3 3 3 3 3 3 3 ...
## $ year : int 1952 1957 1962 1967 1972 1977 1982 1987 1992 1997 ...
## $ lifeExp : num 28.8 30.3 32 34 36.1 ...
## $ pop : int 8425333 9240934 10267083 11537966 13079460 14880372 12881816 13867957 16317921 22227415 ...
## $ gdpPercap: num 779 821 853 836 740 ...
summary(data.gap)
## country continent year lifeExp
## Afghanistan: 12 Africa :624 Min. :1952 Min. :23.60
## Albania : 12 Americas:300 1st Qu.:1966 1st Qu.:48.20
## Algeria : 12 Asia :396 Median :1980 Median :60.71
## Angola : 12 Europe :360 Mean :1980 Mean :59.47
## Argentina : 12 Oceania : 24 3rd Qu.:1993 3rd Qu.:70.85
## Australia : 12 Max. :2007 Max. :82.60
## (Other) :1632
## pop gdpPercap
## Min. :6.001e+04 Min. : 241.2
## 1st Qu.:2.794e+06 1st Qu.: 1202.1
## Median :7.024e+06 Median : 3531.8
## Mean :2.960e+07 Mean : 7215.3
## 3rd Qu.:1.959e+07 3rd Qu.: 9325.5
## Max. :1.319e+09 Max. :113523.1
##
Si quieres hacer lo mismo para una de las variables en la base de datos gapminder, entonces (Ayuda: para acceder a una variable de una base de datos usa el operador $):
View(data.gap$lifeExp)
head(data.gap$lifeExp)
## [1] 28.801 30.332 31.997 34.020 36.088 38.438
tail(data.gap$lifeExp)
## [1] 60.363 62.351 60.377 46.809 39.989 43.487
str(data.gap$lifeExp)
## num [1:1704] 28.8 30.3 32 34 36.1 ...
summary(data.gap$lifeExp)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 23.60 48.20 60.71 59.47 70.85 82.60
Ejercicios
Probar cada una de estas funciones con los datos txhousing.
Probar cada una de estas funciones con una de las variables de los datos txhousing
En R puedes crear nuevas variables a partir de las variables que ya tienes disponible en tu base de datos. Por ejemplo,
Puedes crear una variable con un conjunto de categorías, a partir de una o más variables numéricas.
Puedes crear una variable con un conjunto de categorías, a partir de una o más variables categóricas.
Puedes crear una variable con un conjunto de categorías, a partir una combinación de variables numéricas y categóricas.
Puedes crear una variable numérica a partir de una o más variables numéricas.
Por ejemplo, para los datos sobre mercado inmobiliario (txhousing), si quieres crear una variable con cuatro categorías que indique el trimestre en el que se da cada registro en la base de datos, lo puedes hacer de la siguiente manera:
data.house$trimestre[data.house$month <= 3] <- 1
data.house$trimestre[data.house$month > 3 & data.house$month <= 6] <- 2
data.house$trimestre[data.house$month > 6 & data.house$month <= 9] <- 3
data.house$trimestre[data.house$month > 9] <- 4
summary(data.house$trimestre)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 1.000 1.000 2.000 2.471 3.000 4.000
# Convirtiendo una variable de clase "num" a clase "chr"
data.house$trimestre.cat <- factor(data.house$trimestre, labels = c("Primero", "Segundo", "Tercero", "Cuarto"))
summary(data.house$trimestre.cat)
## Primero Segundo Tercero Cuarto
## 2208 2208 2116 2070
Ejercicios
Para los datos sobre mercado inmobiliario (txhousing) crea las siguientes variables:
Crea una variable numérica que indique el volumen de ventas promedio a partir de las variables sales y volume.
Crea una variable con tres categorías que indique el nivel de ventas a partir de las variables sales y volume:
Qué se te ocurre si quieres crear una variable con un conjunto de categorías, a partir una combinación de variables numéricas y categóricas? Sé creativo!!! (pero que tenga sentido)
Para acceder a los nombres de las variables de tu base de datos puedes usar la función names() o colnames(). De igual forma, si quieres acceder a los nombres de las filas, puedes usar la función rownames().
Para cambiar el nombre de las variables de un conjunto de datos, puedes usar la función rename() del paquete plyr.
library(plyr)
names(data.house)
## [1] "city" "year" "month" "sales"
## [5] "volume" "median" "listings" "inventory"
## [9] "date" "trimestre" "trimestre.cat"
colnames(data.house)
## [1] "city" "year" "month" "sales"
## [5] "volume" "median" "listings" "inventory"
## [9] "date" "trimestre" "trimestre.cat"
head(rownames(data.house))
## [1] "1" "2" "3" "4" "5" "6"
new.data.house <- rename(data.house, c(city="ciudad", year="año", month = "mes"))
names(new.data.house)
## [1] "ciudad" "año" "mes" "sales"
## [5] "volume" "median" "listings" "inventory"
## [9] "date" "trimestre" "trimestre.cat"
La forma más simple de hacer subconjuntos de datos es usando la función subset(). Esta función permite hacer subconjuntos de datos tanto por condiciones de fila (argumento subset), de columna (argumento select), o de ambos.
Por ejemplo, para los datos sobre mercado inmobiliario (txhousing), crea un subconjunto de datos con las variables listings e inventory para la ciudad de Tyler.
Tyler.data <- subset(data.house, city == "Tyler", select=c(listings, inventory))
head(Tyler.data)
## # A tibble: 6 x 2
## listings inventory
## <dbl> <dbl>
## 1 1438 8.4
## 2 1483 8.7
## 3 1438 8.4
## 4 1564 9.2
## 5 1564 9.2
## 6 1585 9.3
Ejercicios
Para los datos sobre mercado inmobiliario (txhousing):
Si tienes dos bases de datos sobre el mismo tema y quieres fusionarlas, puedes usar la función merge(). Debes tener presente que las dos bases de datos deben tener por lo menos una columna en común. En este caso no es necesario que los dos conjuntos de datos sean de la misma dimensión.
Por ejemplo, si dividimos la base de datos txhousing en dos: una con las variables categóricas, y otra con las variables numéricas, y conservamos las variables de identificación de cada registro, y luego queremos volver a fusionarlas en una sóla base de datos. El código sería el siguiente (Nota: Las variables de identificación de cada registro son: city, year y month, ¿por qué?):
data.cuanti <- subset(data.house, select=c(city, year, month, sales, volume,
median, listings, inventory))
data.cuali <- subset(data.house, select=c(city, year, month, date, trimestre,
trimestre.cat))
data.merge <- merge(data.cuali, data.cuanti, by = c("city", "year", "month"))
dim(data.merge)
## [1] 8602 11
dim(data.house)
## [1] 8602 11
También podemos fusionar conjuntos de datos por filas (rbind()) o por columnas (cbind()). Cuando se hace por filas, las dos bases de datos deben tener el mismo número de columnas. Cuando se hace por columnas, las dos bases de datos deben tener el mismo número de filas.
Ejercicios
Fusiona por columnas las bases de datos data.cuali y data.cuanti. ¿Qué diferencia hay con el último merge que hiciste?.
Fusiona por filas las dos bases de datos que obtuviste en el primer ejercicio de la anterior subsección.
En R tenemos disponibles distintos sistemas gráficos, aunque los más comunes son:
Sistema gráfico base de R (autor: R Core Team and contributors). El núcleo (core en inglés) gráfico en R se encuentra en los paquetes graphics (contiene las funciones de gráficos base: plot, hist, etc.) y grDevices (que implementa los distintos dispositivos gráficos: pdf, ps, png, …).
lattice (autor:Deepayan Sarkar). El libro Lattice. Multivariate Data Visualization with R (http://www.springer.com/gp/book/9780387759685) proporciona una gran cantidad de ejemplos (con código `R’).
ggplot2 (autor: Hadley Wickham). En https://ggplot2-book.org/ podéis encontrar la versión online de de la tercera edición del libro ggplot2: elegant graphics for data analysis. Más detalles en la sesión de la semana que viene!
Independientemente del sistema gráfico que empleemos, el tipo de gráfico que seleccionemos va a depender de:
La información que queramos extraer de los datos.
El tipo de variable (cuantitativa o cualitativa).
En número de variables que queramos graficar (describir la posible relación que hay entre ellas).
En esta sesión ilustraremos los gráficos más comunes del paquete graphics. Recuerda que siempre puedes ir a los ejemplos de la ayuda de cada función para aprender otras opciones!
Antes de ver las principales funciones que podemos emplear, veamos algunos ejemplos que nos ofrece R
demo(graphics)
Para realizar el caso práctico en esta parte del curso vamos a emplear el conjunto de datos titanic3 del paquete PASWR (En el material de clase está en formato .xlsx). El conjunto de datos contiene información sobre l@s pasajer@s del barco Titanic. Está formado por 1309 observaciones (pasajer@s) y contamos con información de 14 variables. El primer paso será cargar (o instalar el paquete) y el conjunto de datos y ver la información con la que contamos:
library(PASWR) # install.packages("PASWR") si no lo tenemos
data(titanic3)
names(titanic3)
## [1] "pclass" "survived" "name" "sex" "age"
## [6] "sibsp" "parch" "ticket" "fare" "cabin"
## [11] "embarked" "boat" "body" "home.dest"
?titanic3
Para este ejercicio nos vamos a centrar en las variables:
pclass Variable cualitativa que indica la clase en la que viajaba la/el pasajera/o: 1st (primera clase), 2nd (segunda clase) y 3rd (tercera clase)
survived Variable cualitativa que indica si la/el pasajera/o sobrevivió o no: 0 (no sobrevivió) e 1 (sobrevivió).
sex Variable cualitativa que indica el sexo: Male (hombre) y Female (mujer).
Este gráfico lo emplearemos con variables cualitativas. El gráfico presenta una barra para cada una de las distintas categorías de la variable, siendo la áltura de la barra la frecuencia (relativa o absoluta) de cada categoría.
# Frecuencias abolutas
fa_pclass <- table(titanic3$pclass)
fa_pclass
##
## 1st 2nd 3rd
## 323 277 709
barplot(fa_pclass)
El gráfico anterior es bastante simple, pero podemos “mejorarlo” de muchas maneras
barplot(fa_pclass,
col = c(1, 2, 3), # Colores para cada una de las barras (1:3)
density = 50, # Trama para el color de las barras
xlab = "Clase", # Texto a aparecer en el eje x de la gráfica
ylab = "Frecuencia absoluta", # Texto a aparecer en el eje y de la gráfica
main = "Tabla de frecuencias absolutas (clase)", # Título
cex.main = 2 # Tamaño de letra para el título
)
Y si queremos las frecuencias relativas, se lo indicamos de la siguiente manera
fr_pclass <- prop.table(fa_pclass)
fa_pclass
##
## 1st 2nd 3rd
## 323 277 709
fr_pclass
##
## 1st 2nd 3rd
## 0.2467532 0.2116119 0.5416348
barplot(fr_pclass,
col = heat.colors(3), # Colores para cada una de las barras
density = 10, # Trama para el color de las barras
xlab = "Clase", # Texto a aparecer en el eje x de la gráfica
ylab = "Frecuencia relativa", # Texto a aparecer en el eje y de la gráfica
main = "Tabla de frecuencias relativas (Clase)", # Título
)
En el gráfico anterior hemos empleado colores de la llamada paleta de colores heat.colors (el número 3 indica que queremos 3 colores de esa paleta). El tema de los colores en R es otro universo. Podéis encotrar más información en las siguientes páginas
Ejercicio
Modifica el gráfico de barras anterior, para que:
Las barras aparezcan unas al lado de las otras (sin espacio).
Las barras aparezcan en sentido horizontal en lugar de vertical.
Juega con los colores
Pista: usa la ayuda asociada a la función barplot().
Otro gráfico habitual para variables cualitativas es el gráfico de sectores, que representa mediante un sector circular (quesito) cada una de las distintas categorías de la variable, siendo su área proporcional a la frecuencia de cada categoría
fa_pclass <- table(titanic3$pclass)
pie(fa_pclass,
col = heat.colors(3), # Colores para cada una de los sectores
main = "Gráfico de sectores (class)"
)
Aunque un grafico de barras para una única variable puede ofrecer información valiosa (ayuda a describir, gráficamente, los datos con los que contamos), su mayor potencial es en aquellas situaciones en las que queremos estudiar y representar gráficamente la (posible) relación que existe entre dos variables cualitativas.
En los siguiente ejemplos, emplearemos los datos titanic3, y representaremos conjuntamente las variables pclass y survived. Sin embargo, antes de nada vamos a transformar nuestra variable survived ya que aunque es una variable cualitativa, en nuestro conjunto de datos está codificada como cuantitativa (numérica) (y eso no es aconsejable!!)
summary(titanic3$survived)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.000 0.000 0.000 0.382 1.000 1.000
titanic3$survived_f <- factor(titanic3$survived, levels = c(0,1), labels = c("No", "Sí"))
summary(titanic3$survived_f)
## No Sí
## 809 500
Lo primero que tenemos que hacer para crear un gráfico de barras para dos variables, es crear una tabla de frecuencias (absolutas o relativas) con las dos variables de intereś
tt <- table(titanic3$survived_f, titanic3$pclass) # Paso 1: crear una tabla de doble entrada (freq. absolutas)
tt
##
## 1st 2nd 3rd
## No 123 158 528
## Sí 200 119 181
colnames(tt)
## [1] "1st" "2nd" "3rd"
rownames(tt)
## [1] "No" "Sí"
Ahora empleamos esa tabla como argumento de la función barplot()
barplot(tt, main = "Survived es apilado dentro de los niveles de pclass",
col = 2:3,
legend.text = TRUE, # incluye una leyenda con las categorías de la variable apilada con el color que la identifica en el gráfico.
xlab = "Clase"
)
Por defecto, la función barplot() toma como referencia la variable que aparece en las columnas de nuestra tabla (en nuestro caso, pclass), y agrupa o apila las categorías de la otra variable (survived_f) dentro de cada categoría de la variable de referencia. Si queremos cambiar la agrupación tenemos que trasponer la tabla (cambiar filas por columnas)
t(tt) # Para trasponer la tabla
##
## No Sí
## 1st 123 200
## 2nd 158 119
## 3rd 528 181
barplot(t(tt), main = "pclass es apilado dentro de los niveles de survived",
col = 2:4,
legend.text = TRUE,
args.legend = list(x = "topleft", cex = 1.5, title = "Clase") # Cambiamos la apariencia de la leyenda
)
También por defecto, la función barplot() nos muestra un gráfico de barras apilado. Si queremos obtener un gráfico de barras con las barras agrupadas en lugar de apiladas, tenemos que especificar beside = TRUE.
barplot(tt, main = "Survived es agrupado dentro de los niveles de pclass",
col = 2:3,
legend.text = TRUE,
beside = TRUE
)
Igual que antes, si trasponemos la tabla, la presentación cambia
barplot(t(tt), main = "pclass es apilado dentro de los niveles de survived",
col = 2:4,
legend.text = TRUE,
beside = TRUE
)
Antes de terminar … ¿Y si queremos las 4 gráficas en una sola? Para ello empleamos la función par(). Esta función permite establecer valores (“características”) por defecto, y que se aplicarán a todos los gráficos que se generen mientras no se cierre la ventana gráfica). Por ejemplo, la opción mfrow permite dividir la ventana en varios gráficos, bg cambiar el color de fondo
par(mfrow = c(2,2), bg = "cornsilk")
barplot(tt, main = "Versión 1", col = 2:3, legend.text = TRUE)
barplot(t(tt), main = "Versión 2", col = 2:4, legend.text = TRUE)
barplot(tt, main = "Versión 3", col = 2:3, legend.text = TRUE, beside = TRUE)
barplot(t(tt), main = "Versión 4", col = 2:4, legend.text = TRUE, beside = TRUE)
Ejercicio
Juega a crear gráficos de barras con las variable suvived_f y sex del conjunto de datos titanic3, u otras variables que consideres interesantes.
RECUERDA: los gráficos de barras tienen sentido con variables cualitativas (factores)!!
Es el gráfico más importante para datos cuantitativos. La filosofía es la misma que el gráfico de barras para datos cualitativos , solo que toma como base la tabla de frecuencias para los datos previamente agrupados. Así, los datos se agrupan en categorías (intervalos) y se representa una barra para cada categoría, siendo su altura la frecuencia (absoluta ou relativa) de cada intervalo. Para representar este gráfico en R empleamos la función hist().
hist(titanic3$age,
xlab = "Edad",
main = "Distribución de la edad de l@s pasajer@s del titanic",
ylab = "Frecuencia absoluta",
col = "blue", # color de relleno
border = "white" # color del borde del rectángulo
)
Por defecto, la función hist() elige atomáticamente el número de intervalos para representar el histograma. Podemos cambiar el número utilizando el argumento breaks (aunque la mayor parte de las veces no será necesario). Además, podemos graficar las frecuencias absolutas en lugar de las relativas usando freq = FALSE
hist(titanic3$age,
breaks = 30, # Número de intervalos
freq = FALSE, # Frecuencias relativas
xlab = "Edad",
main = "Distribución de la edad de l@s pasajer@s del titanic",
ylab = "Frecuencia absoluta",
col = "#b347f0", # color de relleno
border = "#ca47f0" # color del borde del rectángulo
)
Además, al gráfico anterior, le podemos añadir más información que consideremos interesante. Por ejemplo, una línea vertical con el valore medio de los datos
hist(titanic3$age,
breaks = 30, # Número de intervalos
freq = FALSE, # Frecuencias relativas
xlab = "Edad",
main = "Distribución de la edad de l@s pasajer@s del titanic",
ylab = "Frecuencia absoluta",
col = "#b347f0", # color de relleno
border = "#ca47f0") # color del borde del rectángulo
abline(v = mean(titanic3$age, na.rm = TRUE), col = "red", lwd = 2)
¿Y si queremos ver la distribución de edad según la clase en la que viajaba o si sobrevivió o no? Pues podemos hacerlo de dos maneras:
Haciendo un gráfico por separado para cada grupo de interés.
Presentando el histograma para cada grupo de interés pero en la misma gráfica (a veces no resulta sencillo de ver).
par(mfrow = c(1, 2)) # Dos gráficos en la misma ventana
hist(titanic3$age[titanic3$survived_f == "Sí"], # Seleccionamos la edad de los supervivientes
breaks = 30,
freq = FALSE,
main = "Supervivientes",
xlab = "Edad")
hist(titanic3$age[titanic3$survived_f == "No"], # Seleccionamos la edad de los no supervivientes
breaks = 30,
freq = FALSE,
main = "No supervivientes",
xlab = "Edad")
Y ahora, los dos gráficos en uno
hist(titanic3$age[titanic3$survived_f == "Sí"],
breaks = 30,
freq = FALSE,
main = "Supervivientes vs No supervivientes",
xlab = "Edad",
col = "green",
density = 30, # Trama para el color de las barras
ylim = c(0, 0.05)) # Rango para el eje y
hist(titanic3$age[titanic3$survived_f == "No"],
breaks = 30,
freq = FALSE,
col = "blue",
density = 30, # Trama para el color de las barras
angle = 135, # Ángulo (para las tramas)
add = TRUE) # Añade el gráfico al anterior!
# Añadimos una leyenda al gráfico
legend ("topright", # Posición de la leyenda
legend = c("Supervivientes", "No supervivientes"), # Texto para la leyenda
col = c("green", "blue"), # Color asociado a cada elemento de la leyenda
lty = 1, # Tipo de línea
bty = "n") # Sin "enmarcar"
Ejercicios
Crea un histograma para la variable fare (precio) del conjunto de datos titanic3.
Crea un histograma para la variable fare (precio) del conjunto de datos titanic3, pero separadamente (bien en un mismo gráfico o en gráficos diferentes) según la clase en la que viajaba la/el pasajera/o.
Ahora trabaja con el conjunto de datos gapminder. Crea un histograma para la variable lifeExp (esperanza de vida), y hazlo separadamente según el continente (variable continent).
El diagrama de cajas o box-plot también se emplea con variables cuantitativas. Es un diagrama simple pero proporciona mucha información. A partir de él se puede observar de forma clara cómo se distribuyen los datos y sus características principales. Además, permite comparar hacer comparaciones de forma sencilla.
boxplot(titanic3$age,
main = "Edad de l@s pasajer@s del Titanic",
ylab = "Edad",
col = "pink",
border = "purple")
Este gráfico está formado por una caja, en la que la base inferior coincide con el primer cuartil (\(Q_1\)), y la base superior con el tercer cuartil (\(Q_3\)). En el interior de la caja se dibuja una línea en la mediana de los datos (\(Q_2\)). Los bigote inferior y superior se corresponden con los siguientes límites
\[LI = min \left\{x_j \mid x_j > Q_1 - 3\left(\frac{Q_3 - Q_1}{2}\right)\right\},\]
\[ LS = max \left\{x_j \mid x_j < Q_3 + 3\left(\frac{Q_3 - Q_1}{2}\right)\right\}. \]
Cualquier valor menor que el límite inferior (LI) o mayor que el límite superior (LS) se consideara un dato atípico (outlier) y se representa en la gráfica con un punto.
Al igual que en el caso del histograma, puede ser de interés ver cómo se distribuye una variable cuantitativa según los valores (categorías o niveles) de una variable cualitativa utilizando un diagrama de cajas. En este caso, siempre es recomendable presentar los resultados en un único gráfico. Además, con la función boxplot() es muy sencillo!!
boxplot(titanic3$age ~ titanic3$survived_f,
main = "Edad de l@s pasajer@s del Titanic",
xlab = "Supervivientes",
ylab = "Edad",
col = c("pink", "purple"))
Podemos, además, cambiar la orientación del gráfico y la etiqueta asociada a cada categoría de la variable categórica
boxplot(titanic3$age ~ titanic3$survived_f,
main = "Edad de l@s pasajer@s del Titanic",
horizontal = TRUE, # boxplot en posición horizontal
xlab = "Edad", # Cuidado aquí. Edad ahora está en el eje x
col = c("pink", "purple"),
ylab = "",
names = c("No sobrevivieron", "Sobrevivieron")) # cambiamos la etiqueta
***
Ejercicios
Crea un boxplot para la variable fare (precio) del conjunto de datos titanic3.
Crea un boxplot para la variable fare (precio) del conjunto de datos titanic3, pero separadamente según la clase en la que viajaba la/el pasajera/o.
Ahora trabaja con el conjunto de datos gapminder. Crea un boxplot para la variable lifeExp (esperanza de vida), y hazlo separadamente según el continente (variable continent).
Hasta ahora hemos visto como graficar tanto variable cualitativas (empleando barplot y pie) como cuantitativas (hist y boxplot). Además, hemos visto como (1) podemos emplear barplot si queremos “estudiar” la relación entre dos variable cualitativas, y (2) podemos usar hist y boxplot para estudiar la relación entre una variable cuantitativa y otra cualitativa (si hay diferencias en la distribución de la variable cuantitativa en función de la variable cualitativa). Nos queda por tanto por ver qué hacemos cuando las dos variable de interés son cuantitativas. Para ello, uno de los gráficos más sencillo (y potentes) es el gráfico de dispersión.
El gráfico de dispersión, permite efectuar un diagnóstico visual de la posible relación (funcional) entre dos variables cuantitativa. La función en R que permite realizar este tipo de gráfico es plot. La función (ver ?plot), tiene un argumento llamado type que sirve para seleccionar el tipo de gráfico a dibujar. Las opciones de type son:
“p” para hacer un gráfico de puntos (es el tipo de gráfico por defecto).
“l” para hacer un gráfico de líneas.
“b” para hacer un gráfico de puntos y líneas (pero las líneas no entran en los puntos).
“c” para hacer un gráfico de líneas (parten de los puntos, sin entrar, pero no se representan).
“o” para hacer un gráfico de puntos y líneas (ahora las líneas entran en los puntos).
“h” para hacer un histograma o un diagrama de barras.
“s” para hacer un diagrama de escalera.
Por defecto la opción es type = "p". Por tanto, si queremos hacer un diagrama de dispersión para representar la nube de puntos no será necesario indicar el tipo de gráfico.
Para los ejemplos siguientes, cambiamos de base de datos, y utilizamos el conjunto de datos gapminder. Lo que nos interesa estudiar es si hay relación entre la renta per capita y la esperanza de vida. Primero de todo, veamos cómo se distribuye cada variable por separado
par(mfrow = c(2,2))
hist(data.gap$gdpPercap, xlab = "Renta per capita", main = "Renta per capita")
hist(data.gap$lifeExp, xlab = "Esperanza de vida", main = "Esperanza de vida")
boxplot(data.gap$gdpPercap, xlab = "Renta per capita", main = "Renta per capita")
boxplot(data.gap$lifeExp, xlab = "Esperanza de vida", main = "Esperanza de vida")
Lo que vemos en la gráfica anterior, es que que la distribución de la renta per cápita es muy asimétrica (muchos valores “atípicos” muy elevados). Esa asimetría sugiere que es preferible, al hacer el gráfico de dispersión, emplear el logaritmo de la renta.
plot(x = log(data.gap$gdpPercap), y = data.gap$lifeExp,
xlab = "Renta per capita (escala logarítmica)",
ylab = "Esperanza de vida")
También lo podríamos haber hecho así
plot(data.gap$lifeExp ~ log(data.gap$gdpPercap),
xlab = "Renta per capita (escala logarítmica)",
ylab = "Esperanza de vida")
Además, podemos “complicar” la cosa un poquito más: ver si la relación que observamos cambia según el continente (variable cualitativa). Eso lo podemos hacer dibujando de color diferente los puntos del gráfico según el continente. Empleamos para ello el argumento col
levels(data.gap$continent)
## [1] "Africa" "Americas" "Asia" "Europe" "Oceania"
plot(data.gap$lifeExp ~ log(data.gap$gdpPercap),
col = (1:5)[data.gap$continent], # Misma longitud que los datos!!
xlab = "Renta per capita (escala logarítmica)",
ylab = "Esperanza de vida")
legend("bottomright",
col = 1:5, # Colores utilizados
pch = 16, # Tipo de punto
legend = levels(data.gap$continent), # Etiqueta asociada a cada color
bty = "n") # Leyenda sin recuadro
Y podemos cambiar el tipo de “punto” para cada continente, empleando el argumeneto pch
levels(data.gap$continent)
## [1] "Africa" "Americas" "Asia" "Europe" "Oceania"
plot(data.gap$lifeExp ~ log(data.gap$gdpPercap),
col = (1:5)[data.gap$continent], # Misma longitud que los datos!!
pch = (1:5)[data.gap$continent], # Misma longitud que los datos!!
cex = 0.5, # Cambiamos el tamaño de cada punto
xlab = "Renta per capita (escala logarítmica)",
ylab = "Esperanza de vida")
legend("bottomright",
col = 1:5, # Colores utilizados
pch = 1:5, # Tipo de punto
legend = levels(data.gap$continent), # Etiqueta asociada a cada color/punto
bty = "n")
Ejercicios
Una vez creado un gráfico, podemos añadir “elementos” a él. Hemos visto algunos a lo largo de la sesión de hoy (abline o legend), pero hay muchos más. Aquí tenéis más que pueden ser de interés:
points() Añade puntos
lines() Añade líneas
abline() Añade una línea paramétrica
legend() Añade una leyenda
mtext() Escribe texto en los márgenes
text() Escribe texto dentro gráfico.
arrows(), segments(), polygon() Dibuja flechas, segmentos y polígonos
title() Añade títulos
identify() y locator() Permiten identificar puntos del gráfico o coordenadas
En esta sesión hemos visto solo una parte pequeña de la funciones que ofrece R para hacer gráficos, pero incluso el sistema gráfico base de R ofrece muchas más funciones. Entre ellas:
symbols() Dibuja símbolos en un gráfico (círculos, rectángulos, estrellas, boxplots o termómetros)
pairs() Gráficos de dispersión multivariantes
matplot() Gráfico de x con una matriz de y’s
coplot() Gráficos de dispersión condicionados
barplot() Gráfico de barras
image() Gráfico de niveles de una matriz
contour() y filled.contour() Líneas de contorno
persp() Gráfico 3-D
Ejemplo
coplot(data.gap$lifeExp ~ log(data.gap$gdpPercap)|data.gap$continent,
xlab = "Renta per capita (escala logarítmica)",
ylab = "Esperanza de vida")
Si trabajamos RStudio y queremos guardar o exportar un gráfico normalmente hacemos lo siguiente:
Ejecutamos el “código” del gráfico que queremos guardar. Este gráfico aparecerá en la pestaña Plots del entorno de trabajo de RStudio (lo hemos visto a lo largo de la sesión)
\(~\)
\(~\)
Al seleccionar la opción Export se desplegará una lista con tres opciones:
\(~\)
\(~\)
\(~\)
\(~\)
Guardar como pdf (Save as pdf…).
Copiar al portapapeles (Copy to clipboard…)
De los muchos sistemas que posee R para hacer gráficos, ggplot2 es uno de los más elegantes y versátiles. Esto se debe a que ggplot2 implementa un sistema coherente para describir y construir gráficos, conocido como la gramática de gráficos. Está diseñado para trabajar en capas, comenzando con una capa que muestra los datos en crudo y luego agregando capas de resúmenes estadísticos y anotaciones.
Más información sobre los fundamentos teóricos de ggplot2 en el artículo: “La gramática de gráficos en capas” (http://vita.had.co.nz/papers/layered-grammar.pdf.
Ventajas de ggplot2:
Su sintaxis es consistente y está basada en la gramática de los gráficos.
Especificación del gráfico a un alto nivel de abstracción.
Muy flexible, tiene muchas funcionalidades.
Para empezar a crear un gráfico con ggplot2 se utiliza la función ggplot(). ggplot() crea un sistema de coordenadas al que puedes agregar capas. El primer argumento de ggplot() es el conjunto de datos que se utilizará en el gráfico. Si corres ggplot(data = data.gap), obtendrás un gráfico vacío (no vamos a mostrarlo).
library(ggplot2) ## install.packages("ggplot2")
## leer el fichero gapminder
## data.gap <- read.table("gapminder.csv", header = TRUE, sep = "", dec = ",")
ggplot(data = data.gap)
Para completar el gráfico debemos agregar una o más capas a ggplot().
La función geom_point() agrega una capa de puntos al gráfico, que crea un diagrama de dispersión (o scatterplot). Cada función geom tiene un argumento de mapping. Este define cómo se “mapean” o se asignan las variables del conjunto de datos a propiedades visuales. El argumento de mapping siempre aparece emparejado con aes() y los argumentos x e y dentro de aes() especifican qué variables asignar a estos ejes. ggplot2 busca la variable asignada en el argumento data, en nuestro caso, data.gap.
Por ejemplo,
ggplot(data = data.gap, mapping = aes(x = gdpPercap, y = lifeExp)) +
geom_point()
El código de ggplot2 se puede traducir a esta plantilla. Para hacer un gráfico, reemplaza las secciones entre corchetes en el siguiente código con un conjunto de datos, una función geom o una colección de mapeos.
ggplot(data = <DATA>) +
<GEOM_FUNCTION>(mapping = aes(<MAPPINGS>))
En lo que sigue mostraremos cómo utilizar y adaptar esta plantilla para crear diferentes tipos de gráficos.
Recuerda también que simpre puedes consultar la ayuda (mediante ?funcion o help(funcion)). Además, ggplot2 tiene una especie de “chuleta” que es muy útil: https://rstudio.com/wp-content/uploads/2015/03/ggplot2-cheatsheet.pdf.
Mapear los datos o las variables a elementos o parámetros visuales:
gdpPercap –> x
lifeExp –> y (en escala \(\log_{10}\))
ggplot(data = data.gap, mapping = aes(x = log10(gdpPercap), y = lifeExp)) +
geom_point()
Como la sintaxis de ggplot se escribe por capas es muy práctico asignar el gráfico y guardarlo en un objeto de R. Por ejemplo, podemos asignar el gráfico anterior a un objeto/variable con nombre p.
p <- ggplot(data = data.gap, mapping = aes(x = log10(gdpPercap), y = lifeExp))
Otros argumentos para aes() son color =, size =, shape =, alpha = etc.
p + geom_point(aes(color = continent))
Ejercicios
ggplot2 incluye muchas funciones geom, cada una de las cuales agrega un tipo de capa diferente a un gráfico:
p + geom_point() + geom_smooth()
## `geom_smooth()` using method = 'gam' and formula 'y ~ s(x, bs = "cs")'
p + geom_point() + geom_smooth(lwd = 3, se = FALSE, method = "lm")
Ahora que conocemos mejor los datos graficaremos sólo los datos de un año determinado. Escogemos el año 1952 y analizamos la relación entre la renta per cápita y la esperanza de vida de los países.
data.gap1952 <- subset(data.gap, year == 1952)
p2 <- ggplot(data = data.gap1952, aes(x = log10(gdpPercap), y = lifeExp))
Probamos otros geom_s y otros aesthetics,
p2 + geom_text(aes(label = country, color = continent, size = pop))
Ejercicios
lifeExp) a lo largo de los años (year)paises5 <- c("Canada", "Turkey", "Spain", "Rwanda", "Cambodia")
data.gap_pais5 <- subset(data.gap, country %in% paises5)
ggplot(data.gap_pais5,
aes(x = year, y = lifeExp, color = country)) +
geom_line() +
geom_point()
Utilizamos facet_wrap() para dividir el gráfico en sub-gráficos o facetas según una variable adicional. Cada faceta muestra un subconjunto de los datos.
ggplot(data = data.gap1952, aes(x = log10(gdpPercap), y = lifeExp)) +
geom_point(alpha = (1/3), size = 3) + ## otras estéticas específicas, fuera del aes()
facet_wrap(~ continent) ## separar grafico segun continente
p2 + geom_text(aes(label = country, color = continent, size = pop)) +
scale_color_brewer(palette = "Dark2") +
scale_size(range = c(5, 15)) +
theme_classic() +
theme(legend.position = "none",
axis.text = element_text(size = 20),
axis.title = element_text(size = 20))
data.gap1952$country_colors <- country_colors[match(data.gap1952$country, names(country_colors))] ## asignar color a cada pais
ggplot(data.gap1952) +
geom_point(aes(gdpPercap, lifeExp, size = pop, color = country)) + ## tamaño del punto segun pop, color segun country
scale_x_log10(breaks = c(300, 1e3, 3e3, 10e3, 30e3)) + ## etiquetas para el eje x
scale_color_manual(values = country_colors) + ## color
labs(title = "Gapminder año 1952", ## etiquetas
x = "Renta per capita (escala log)",
y = "Esperanza de vida al nacer (años)",
color = "Continente", size = "Poblacion") +
theme_light() + ## tema
theme(legend.position = "none")
## crear survived2 variable cualitativa (tipo factor)
titanic3$survived2 <- factor(titanic3$survived, labels = c("No", "Si"))
ggplot(data = titanic3, mapping = aes(x = survived2, fill = pclass)) +
geom_bar(stat = "count", position = "dodge", alpha = 0.7) + ## stat, position, alpha
scale_fill_manual(name = "Clase", values = c("#E69F00", "#56B4E9", "#009E73")) + ## otros colores para el fill
xlab("Supervivientes") + ylab("") + ggtitle("Pasajeros del Titanic") + ## etiquetas y titulo
theme_minimal() ## tema
Y crear muchísimos más gráficos!! Y GIF-s de datos!! https://simplystatistics.org/2019/08/28/you-can-replicate-almost-any-plot-with-ggplot2/
library(gganimate)
ggplot(gapminder, aes(gdpPercap, lifeExp, size = pop, colour = country)) +
geom_point(alpha = 0.7) +
geom_text(aes(label = country)) +
scale_colour_manual(values = country_colors) +
scale_size(range = c(2, 12)) +
scale_x_log10() +
facet_wrap(~continent) +
theme(legend.position = 'none') +
labs(title = 'Year: {frame_time}', x = 'GDP per capita', y = 'life expectancy') +
transition_time(year)
Para guardar el gráfico, ggsave():
ggsave(
filename = "mi_plot.png",
plot = my_plot,
width = 10,
height = 8,
dpi = 100,
device = "png"
)
En esta sección presentaremos algunos de los elementos básicos para la programación en R. Hablaremos sobre las funciones condicionales, bucles, y otras funciones más avanzadas que tienen como objetivo ayudara a evitar los bucles (los cuales son normalmente muy lentos en R).
La clave de la programación en R está en combinar adecuadamente todos los elementos que hemos ido aprendiendo hasta ahora, para crear funciones (y más adelante, paquetes) con el objetivo de automatizar los cálculos y evitar así, hacer los mismos análisis una y otra vez.
Normalmente, cuando trabajamos en R, no nos ponemos directamente a definir funciones. Primero, empezamos haciendo los análisis o cálculos que necesitamos. Cuando vemos, que repetimos una y otra vez el mismo proceso para hacer estos cálculos o análisis, definimos las funciones. Cuando tengamos unas cuantas funciones definidas para hacer unos análisis, podemos crear nuevos paquetes. La idea es ir mejorando el código con el objetivo de que nos sea fácil implementarlo en vez de ir copiando y pegando el mismo código una y otra vez. Leer por ejemplo, lo que dice Hadley Wickham acerca de la creación de paquetes en el libro R Packages (http://r-pkgs.had.co.nz/): “Writing a package can seem overwhelming at first. So start with the basics and improve it over time. It doesn’t matter if your first version isn’t perfect as long as the next version is better”.
if(), if…else, ifelse()if()El código para poder trabajar con la función if()es la siguiente:
if(condición){
lo que queráis que se haga si se cumple la condición
}
Si la condición se cumple, es decir, si R entiende como TRUE la condición indicada, entonces, ejecutará lo que se le indica que haga entre los corchetes {}. Vamos a ver un ejemplo simple:
x <- 5
if(x > 0){
"Es un número positivo"
}
## [1] "Es un número positivo"
En el ejemplo de arriba, como x coge un valor positivo, R ejecuta lo que está dentro de {}. En cambio, si x coge un valor que no sea mayor que 0, entonces, no imprime nada:
x <- -5
if(x > 0){
"Es un número positivo"
}
Pero, ¡cuidado! Si en vez de un número, metemos un vector, R te devuelve un aviso de que solo trabajará con el primer elemento del vector:
x <- c(-5,0,5)
if(x > 0){
"Es un número positivo"
}
## Warning in if (x > 0) {: la condición tiene longitud > 1 y sólo el primer
## elemento será usado
if...elseEsta es la sintaxis general:
if(condición){
lo que queráis que se haga si se cumple la condición
} else {
lo que queráis que se haga si NO se cumple la condición
}
Lo entenderemos mejor con un ejemplo:
x <- -5
if(x > 0){
"Es un número positivo"
} else {
"No es un número positivo"
}
## [1] "No es un número positivo"
Como en el caso anterior, si le metemos un vector, solo utiliza el primer elemento:
x <- c(-5,0,5)
if(x > 0){
"Es un número positivo"
} else {
"No es un número positivo"
}
## Warning in if (x > 0) {: la condición tiene longitud > 1 y sólo el primer
## elemento será usado
## [1] "No es un número positivo"
ifelse()Código general:
ifelse(condición,
lo que queráis que se haga si se cumple la condición,
lo que queráis que se haga si NO se cumple la condición)
Ejemplo:
x <- -5
ifelse(x > 0, "Es un número positivo", "No es un número positivo")
## [1] "No es un número positivo"
En este caso, podemos meter los vectores y ejecutará el código para cada uno de los elementos del vector:
x <- c(-5,0,5)
ifelse(x > 0, "Es un número positivo", "No es un número positivo")
## [1] "No es un número positivo" "No es un número positivo"
## [3] "Es un número positivo"
for()El código general de for() es la siguiente:
for(para cada elemento en una secuencia){
lo que queráis que se haga para cada elemento
}
Un ejemplo fácil (y no muy práctico) para entender mejor el concepto:
for(i in c(1:10)){
print(i*2)
}
## [1] 2
## [1] 4
## [1] 6
## [1] 8
## [1] 10
## [1] 12
## [1] 14
## [1] 16
## [1] 18
## [1] 20
Siguiendo con el ejemplo del apartado anterior, dentro de for() podemos meter las funciones condicionales que se han descrito anteriormente. Por ejemplo:
for(x in c(-3,7,-1,2,3,0,-5,-1,1,4)){
if(x > 0){
print("Es un valor positivo")
} else {
print("No es un valor positivo")
}
}
## [1] "No es un valor positivo"
## [1] "Es un valor positivo"
## [1] "No es un valor positivo"
## [1] "Es un valor positivo"
## [1] "Es un valor positivo"
## [1] "No es un valor positivo"
## [1] "No es un valor positivo"
## [1] "No es un valor positivo"
## [1] "Es un valor positivo"
## [1] "Es un valor positivo"
A continuación, un ejemplo que puede llegar a ser un poco más práctico. Si tenemos una base de datos con distintas columnas, podemos calcular por ejemplo la media de cada una de las columnas con un for(). Esto puede ser práctico si queremos calcular por ejemplo la media (o cualquier otra cosa) de muchas columnas a la vez.
x1 <- rnorm(20, mean = 0, sd = 1)
x2 <- rnorm(20, mean = 2, sd = 2)
x3 <- rnorm(20, mean = 4, sd = 1)
df <- data.frame(x1,x2,x3)
#Podemos calcular la media de cada una de las columnas una a una:
mean(df[,1])
## [1] 0.1764135
mean(df[,2])
## [1] 1.954325
mean(df[,3])
## [1] 4.128299
#O todo a la vez, con un for():
for(i in c(1:3)){
print(mean(df[,i]))
}
## [1] 0.1764135
## [1] 1.954325
## [1] 4.128299
apply()En R, normalmente los bucles no son muy eficientes, tardan mucho, y suele ser mejor intentar evitarlos. Por ejemplo, recordemos uno de los ejemplos anteriores:
for(i in c(1:10)){
print(i*2)
}
## [1] 2
## [1] 4
## [1] 6
## [1] 8
## [1] 10
## [1] 12
## [1] 14
## [1] 16
## [1] 18
## [1] 20
En R, se podría hacer esto de una forma mucho más sencilla, directamente multiplicando el vector c(1:10) por el 2, y evitando así el uso de los bucles:
c(1:10)*2
## [1] 2 4 6 8 10 12 14 16 18 20
Hay otras funciones definidas en R que nos pueden ayudar a evitar los bucles. La función apply() es una de ellas. Esta es su sintaxis general:
apply(vector o matriz o dataframe,
dígito 1 para las filas y 2 para las columnas,
función que queremos aplicarles a cada una de las filas o columnas)
Por ejemplo, para el data frame que hemos definido anteriormente df, hemos calculado la media de cada una de sus columnas mediante un for(). Podríamos hacer lo mismo con un la función apply() de la siguiente forma:
apply(df, 2, mean)
## x1 x2 x3
## 0.1764135 1.9543250 4.1282992
Si tenemos muchas columnas, la función apply() es mucho más rápida que for(). De la misma forma, si quisiéramos calcular la media de cada una de las filas, lo haríamos así:
apply(df, 1, mean)
## [1] 1.898973 2.805474 1.499359 2.050830 1.845628 1.333757 2.008513
## [8] 2.578463 1.568977 2.215978 2.710404 1.360898 3.015584 1.727979
## [15] 2.016805 3.195731 1.724419 1.640190 2.520545 2.008414
También podemos crear una función propia para aplicarlo dentro de la función apply(). Por ejemplo:
mifuncion <- function(x){
y <- mean(x) + 2
return(y)
}
apply(df, 2, mifuncion)
## x1 x2 x3
## 2.176414 3.954325 6.128299
Ejercicios
Ejercicio 1
Escribe una función que, dados dos vectores v1 y v2, devuelve la media (mean) y la desviación típica (sd) de los dos vectores.
La función deberá tener un tercer argumento que se llame pintargrafico, donde si pintargrafico=TRUE entonces dibuje un gráfico de dispersión para los dos vectores. Añade además la siguiente línea de regresión al gráfico en color rojo: abline(lm(v1 ~ v2)).
Prueba la función anterior con los siguientes vectores:
v1 <- c(5.5,2.8,7.0,6.2,7.1,8.2)
v2 <- c(5.2,3.5,6.1,6.5,6.8,7.2)
Ejercicio 2
Escribe una función que, dado un vector v3, devuelva la media de sus valores negativos, y la media de sus valores positivos.
Prueba la función definida con el siguiente vector:
v3 <- c(2,-2, 4, -1,3,-3,-5)
Ejercicio 1
twovFunction <- function(v1, v2, pintargrafico=FALSE) {
ans <- c(v1.mean=mean(v1), v1.sd = sd(v1),
v2.mean=mean(v2), v2.sd = sd(v2))
if(pintargrafico==TRUE){
plot(v1~v2)
abline(lm(v1~v2), col="red")
}
return(ans)
}
twovFunction(v1, v2)
## v1.mean v1.sd v2.mean v2.sd
## 6.133333 1.869403 5.883333 1.352652
twovFunction(v1, v2, pintargrafico = TRUE)
## v1.mean v1.sd v2.mean v2.sd
## 6.133333 1.869403 5.883333 1.352652
Ejercicio 2
meanvFunction <- function(vector) {
PositiveMean <- sum(vector[vector > 0])/length(vector[vector>0])
NegativeMean <- sum(vector[vector < 0])/length(vector[vector<0])
ans <- c(PositiveMean = PositiveMean, NegativeMean = NegativeMean)
return(ans)
}
v3 <- c(2,-2, 4, -1,3,-3,-5)
meanvFunction(vector=v3)
## PositiveMean NegativeMean
## 3.00 -2.75
R Cookbook, 2nd Edition (J.D. Long and Paul Teetor): https://rc2e.com/
R para principantes (Juan Bosco Mendoza Vega): https://bookdown.org/jboscomendoza/r-principiantes4/
R for Data Science (Hadley Wickham and Garrett Grolemund): https://r4ds.had.co.nz/
Introduction to Data Science (Rafael A Irizarry): https://leanpub.com/datasciencebook
ggplot2: Elegant Graphics for Data Analysis (Hadley Wickham): https://ggplot2-book.org/
Text mining with R (Julia Silge and David Robinson): https://www.tidytextmining.com/
Advanced R (Hadley Wickham): http://adv-r.had.co.nz/
Hands-On Programming with R (Garrett Grolemund): https://rstudio-education.github.io/hopr/
R packages (Hadley Wickham): http://r-pkgs.had.co.nz/
Cheatsheets R: https://rstudio.com/wp-content/uploads/2016/10/r-cheat-sheet-3.pdf y https://rstudio.com/resources/cheatsheets/
Curso de introduccion R-Ladies Melbourne: https://resbaz.github.io/RLadies-Intro-R-workshop/
Curso de introducción R-Ladies Barcelona: https://github.com/rladies/meetup-presentations_barcelona/tree/master/20190328_introR
Data Visualisaton: https://socviz.co/lookatdata.html
ggplot2: https://djnavarro.github.io/satrdayjoburg/slides/#1
R Tutorials for Beginners: Learning R programming: https://www.guru99.com/r-tutorial.html
Programming with R: http://swcarpentry.github.io/r-novice-inflammation/
R for Reproducible Cientific Analysis: https://swcarpentry.github.io/r-novice-gapminder/
R para usuarios de Excel: https://psicologiadedatos.wordpress.com/2014/10/16/por-que-r-es-mejor-que-excel/, https://rfortherestofus.com/2019/06/a-guide-to-r-for-excel-users/, https://www.rforexcelusers.com/
gifs in R: https://paulvanderlaken.com/2017/11/15/advanced-gifs-in-r/